home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGSCAL / INLINE.LZH / INLINE.PAS < prev    next >
Pascal/Delphi Source File  |  1986-11-13  |  53KB  |  1,976 lines

  1.                              {Inline19}
  2.  
  3. (*********  Source code Copyright 1986, by L. David Baldwin   *********)
  4.  
  5. {Compiling with mAx=2000 will give sufficient heap for most applications
  6.  and prevent overwriting COMMAND.COM in most cases.}
  7.  
  8. {
  9. 19 Vers 2.11
  10.    Fix bug in CallJmp and ShortJmp which didn't restrict short
  11.    jump range properly.
  12.    Fix bug which didn't allow CALL or JMP register. (CALL BX).
  13. 18 Vers 2.1
  14.    Fix bug in Accum which occasionally messed up IN and OUT instr.
  15.    Fix unintialized function in getnumber for quoted chars.
  16. 17 Vers 2.03
  17.     Change GetSymbol to accept about anything after '>' or '<'
  18.     Add 'NEW' pseudoinstruction.
  19.     Fix serious bug in defaultextension.
  20.     Add Wait_Already to prevent 2 'WAIT's from occuring.
  21.     Use 'tindex<maxbyte' comparison rather than <= which won't work
  22.     with integer comparison in this case.
  23. }
  24. {$v-}
  25. PROGRAM Inline_Asm;
  26.  
  27. const
  28.   CommentColumn = 25;     {column where comments start in object file}
  29.   symbolleng = 32;        {maximum of 32 char symbols}
  30.   cr = 13; lf = 10; tab = 9;
  31.   maxbyte = MaxInt;
  32.   bigstringsize = 127;
  33.  
  34.   signon1 : string[32] =
  35.  
  36.             ^m^j'Inline Assembler, Vers 2.11';
  37.  
  38.   signon2 : string[43] =
  39.  
  40.             ^m^j'(C) Copyright 1986 by L. David Baldwin'^m^j;
  41.  
  42. type
  43.   filestring = string[64];
  44.   symstring = string[symbolleng];
  45.   indxreg = (bx, si, di, bp, none);
  46.   indxset = set of indxreg;
  47.   ptrtype = (bptr, wptr, dwptr, qwptr, tbptr, unkptr); {keep order}
  48.   string4 = string[4];
  49.   string5 = array[1..5] of Char;
  50.   symtype = (address, disp8, disp16, othersym, EOLsym, identifier, jmpdist,
  51.     lfbrack, rtbrack, plus, comma, STsym);
  52.   table = array[0..20] of symstring; {fake}
  53.   bigstring = string[bigstringsize]; {125 chars on a turbo line}
  54.   label_info_ptr = ^label_info;
  55.   label_info = record
  56.                  name : symstring;
  57.                  bytecnt : Integer;
  58.                  next : label_info_ptr;
  59.                end;
  60.   fixup_info_ptr = ^fixup_info;
  61.   fixup_info = record
  62.                  name : symstring;
  63.                  indx, indx2, fix_pt : Integer;
  64.                  jmptype : (short, med);
  65.                  prev, next : fixup_info_ptr;
  66.                end;
  67.  
  68. var
  69.   NoAddrs, aerr, symbol, str_start, TheEnd, NewFnd, st_first,
  70.   displace, wordd, bits_7, Wait_Already : Boolean;
  71.   Addr : Integer;
  72.   sym : symtype;
  73.   modebyt, reg1, reg2, w1, w2, sti_val : Integer;
  74.   SaveOfs, DataVal : record
  75.                        symb : Boolean;
  76.                        sname : symstring;
  77.                        value : Integer;
  78.                      end;
  79.   irset : indxset;
  80.   rmm, md : Integer;
  81.   ByWord : ptrtype;
  82.   byt, signext : Byte;
  83.   tindex, tindex0, column, I, ByteCount : Integer;
  84.   TextArray : array[0..maxbyte] of Char;
  85.  
  86.   Lsid : symstring;
  87.   Str8 : array[1..9] of Char; {the following 4 are at the same location}
  88.   Str : string5 absolute Str8;
  89.   id2 : array[1..2] of Char absolute Str8;
  90.   id3 : array[1..3] of Char absolute Str8;
  91.   Uch, Lch : Char;
  92.   Chi, OldChi : Integer;
  93.   out, inn : Text;
  94.  
  95.   start_col : Integer;
  96.   st : bigstring;
  97.   firstlabel, pl : label_info_ptr;
  98.   firstfix, pf : fixup_info_ptr;
  99.  
  100. {-------------DefaultExtension}
  101. PROCEDURE DefaultExtension(extension:filestring;VAR infile,name :filestring);
  102. {Given a filename, infile, add a default extension if none exists. Return
  103.  also the name without any extension.}
  104. var
  105.  I,J : Integer;
  106.  temp : filestring;
  107. begin
  108. I:=Pos('..',infile);
  109. if I=0 then
  110.   temp:=infile
  111. else
  112.   begin   {a pathname starting with ..}
  113.   temp:=Copy(infile,I+2,64);
  114.   I:=I+1;
  115.   end;
  116. J:=Pos('.',temp);
  117. if J=0 then
  118.   begin
  119.   name := infile;
  120.   infile:=infile+'.'+extension;
  121.   end
  122. else name:=Copy(infile,1,I+J-1);
  123. end;
  124.  
  125. {-------------Space}
  126. PROCEDURE Space(N : Integer);
  127. var I : Integer;
  128. begin for I := 1 to N do Write(' '); end;
  129.  
  130. {-------------Error}
  131. PROCEDURE Error(ii : Integer; S : bigstring);
  132. begin
  133. if not aerr then
  134.   begin
  135.   WriteLn(st);
  136.   Space(start_col+ii-4);
  137.   Write('^Error');
  138.   if Length(S) > 0 then
  139.     begin Write(', '); Write(S); end;
  140.   WriteLn;
  141.   aerr := True;
  142.   end;
  143. end;
  144.  
  145. {the following are definitions and variables for the parser}
  146. var segm, nvalue : Integer;
  147. symname : symstring;
  148. {end of parser defs}
  149.  
  150. {-------------GetCh}
  151. PROCEDURE GetCh;
  152.   {return next char in uch and lch with uch in upper case.}
  153. begin
  154. if Chi <= Ord(st[0]) then Lch := st[Chi] else Lch := Chr(cr);
  155. Uch := UpCase(Lch);
  156. Chi := Chi+1;
  157. end;
  158.  
  159. {-------------skipspaces}
  160. PROCEDURE skipspaces;
  161. begin
  162. while (Uch = ' ') or (Uch = Chr(tab)) do GetCh;
  163. end;
  164.  
  165. {-------------getdec}
  166. FUNCTION getdec(var v : Integer) : Boolean;
  167. const ssize = 8;
  168. var
  169.   S : string[ssize];
  170.   getd : Boolean;
  171.   code : Integer;
  172. begin
  173. getd := False;
  174. S := '';
  175. while (Uch >= '0') and (Uch <= '9') do
  176.   begin
  177.   getd := True;
  178.   if Ord(S[0]) < ssize then S := S+Uch;
  179.   GetCh;
  180.   end;
  181. if getd then
  182.   begin
  183.   Val(S, v, code);
  184.   if code <> 0 then Error(Chi, 'Bad number format');
  185.   end;
  186. getdec := getd;
  187. end;
  188.  
  189. {-------------gethex}
  190. FUNCTION gethex(var h : Integer) : Boolean;
  191. var digit : Integer;        {check for '$' before the call}
  192. begin
  193. h := 0; gethex := False;
  194. while (Uch in ['A'..'F', '0'..'9']) do
  195.   begin
  196.   gethex := True;
  197.   if (Uch >= 'A') then digit := Ord(Uch)-Ord('A')+10
  198.     else digit := Ord(Uch)-Ord('0');
  199.   if h and $F000 <>0 then Error(Chi, 'Overflow');
  200.   h := (h shl 4)+digit;
  201.   GetCh;
  202.   end;
  203. end;
  204.  
  205. {-------------getnumber}
  206. FUNCTION getnumber(var N : Integer) : Boolean;
  207.   {get a number and return it in n}
  208. var term : Char;
  209.   err : Boolean;
  210. begin
  211. N := 0;
  212. if Uch = '(' then GetCh;    {ignore ( }
  213. if (Uch = '''') or (Uch = '"') then
  214.   begin
  215.   getnumber := True;
  216.   term := Uch; GetCh; err := False;
  217.   while (Uch <> term) and not err do
  218.     begin
  219.     err := N and $ff00 <> 0;
  220.     N := (N shl 8)+Ord(Lch);
  221.     GetCh;
  222.     if err then Error(Chi, 'Overflow');
  223.     end;
  224.   GetCh;                    {use up termination char}
  225.   end
  226. else if Uch = '$' then
  227.   begin                     {a hex number}
  228.   GetCh;
  229.   if not gethex(N) then Error(Chi, 'Hex number exp');
  230.   getnumber := True;
  231.   end
  232. else
  233.   getnumber := getdec(N);   {maybe a decimal number}
  234. if Uch = ')' then GetCh;    {ignore an ending parenthesis}
  235. end;
  236.  
  237. {-------------getexpr}
  238. FUNCTION getexpr(var rslt : Integer) : Boolean;
  239. var
  240.   rs1, rs2, SaveChi : Integer;
  241.   Pos, Neg : Boolean;
  242. begin
  243. SaveChi := Chi;
  244. getexpr := False;
  245. skipspaces;
  246. Neg := Uch = '-';
  247. Pos := Uch = '+';
  248. if Pos or Neg then GetCh;
  249. if getnumber(rs1) then
  250.   begin
  251.   getexpr := True;
  252.   if Neg then rs1 := -rs1;
  253.   if (Uch = '+') or (Uch = '-') then
  254.     if getexpr(rs2) then
  255.       rs1 := rs1+rs2;       {getexpr will take care of sign}
  256.   rslt := rs1;
  257.   end
  258. else
  259.   begin
  260.   Chi := SaveChi-1; GetCh;
  261.   end;
  262. end;
  263.  
  264. {$v+}
  265. {-------------getsymbol}
  266. FUNCTION getsymbol(var S : symstring) : Boolean;
  267. const symchars : set of Char = ['A'..'Z', '0'..'9', '_', '+', '-','$','*'];
  268. begin
  269. if Uch in symchars then
  270.   begin
  271.   getsymbol := True;
  272.   S[0] := Chr(0);
  273.   while Uch in symchars do
  274.     begin
  275.     if Ord(S[0]) < symbolleng then S := S+Uch;
  276.     GetCh;
  277.     end
  278.   end
  279. else getsymbol := False;
  280. end;
  281. {$v-}
  282.  
  283. {-------------getaddress}
  284. FUNCTION getaddress : Boolean;
  285. var result : Boolean;
  286.   SaveChi : Integer;
  287. begin
  288. result := False; SaveChi := Chi;
  289. if getexpr(segm) then
  290.   begin
  291.   skipspaces;
  292.   if Uch = ':' then
  293.     begin
  294.     GetCh; skipspaces;
  295.     result := getexpr(nvalue);
  296.     end;
  297.   end;
  298. getaddress := result;
  299. if not result then
  300.   begin Chi := SaveChi-1; GetCh; end;
  301. end;
  302.  
  303. {-------------errnull}
  304. PROCEDURE errnull;
  305. begin Error(Chi, ''); end;
  306.  
  307. {-------------errincorrect}
  308. PROCEDURE errincorrect;
  309. begin Error(Chi, 'Incorrect or No Operand'); end;
  310.  
  311. {-------------segmerr}
  312. PROCEDURE segmerr;
  313. begin Error(Chi, 'Segm Reg not Permitted'); end;
  314.  
  315. {-------------wordreg}
  316. PROCEDURE wordreg;
  317. begin Error(Chi, 'Word Reg Exp'); end;
  318.  
  319. {-------------datalarge}
  320. PROCEDURE datalarge;
  321. begin Error(Chi, 'Data Too Large'); end;
  322.  
  323. {-------------chk_bwptr}
  324. PROCEDURE chk_bwptr;
  325. begin
  326. if ByWord >= dwptr then Error(Chi, 'BYTE or WORD Req''d');
  327. end;
  328.  
  329. {-------------bytesize}
  330. FUNCTION bytesize(Val : Integer) : Boolean;
  331.   {return true if val is a byte}
  332. begin
  333. bytesize := (Hi(Val) = 0) or (Val and $ff80 = $ff80);
  334. end;
  335.  
  336. {-------------readbyte}
  337. FUNCTION readbyte : Boolean;
  338. var rb : Boolean;
  339. begin
  340. rb := getexpr(nvalue);
  341. if rb then
  342.   if bytesize(nvalue) then
  343.     byt := Lo(nvalue)
  344.   else datalarge;
  345. readbyte := rb;
  346. end;
  347.  
  348. {-------------matchlst}
  349. FUNCTION matchlst(var table; size, maxindx : Integer; var indx : Integer) :
  350.   Boolean;                  {see if str8 matches any string in a table}
  351. var ca : array[0..MaxInt] of Char absolute table;
  352.   rslt : Boolean;
  353.  
  354.   FUNCTION eqarray(var a1; N : Integer) : Boolean;
  355.   type bigarray = array[1..MaxInt] of Char;
  356.   var
  357.     b1 : bigarray absolute a1;
  358.     I : Integer;
  359.   begin
  360.   for I := 1 to N do
  361.     if b1[I] <> Str8[I] then
  362.       begin eqarray := False; Exit; end;
  363.   eqarray := Str8[N+1] = ' '; {must have blank on end for complete match}
  364. end;
  365.  
  366. begin
  367. indx := 0; rslt := False;
  368. while (indx <= maxindx) and not rslt do
  369.   if eqarray(ca[indx*size], size) then
  370.     rslt := True
  371.   else
  372.     indx := indx+1;
  373. matchlst := rslt;
  374. end;
  375.  
  376. {-------------getstring}
  377. PROCEDURE getstring;
  378.   {Fill in lsid, str8, str, id2,id3.  They are, in fact, all in the
  379.    same locations}
  380. var I : Integer;
  381. begin
  382. skipspaces;
  383. Lsid := '          ';
  384. I := 1;
  385. if (Uch >= 'A') and (Uch <= 'Z') then
  386.   begin
  387.   while (Uch >= 'A') and (Uch <= 'Z') or (Uch >= '0') and (Uch <= '9') do
  388.     begin
  389.     if I <= symbolleng then
  390.       begin Lsid[I] := Uch; I := I+1; end;
  391.     GetCh;
  392.     end;
  393.   end;
  394. Lsid[0] := Chr(I-1);
  395. Move(Lsid[1], Str8, 9);     {Fill in str8,str,id2,id3}
  396. end;
  397.  
  398. {-------------InsertChr}
  399. PROCEDURE InsertChr(C : Char);
  400. begin
  401. if tindex < maxbyte then
  402.   begin
  403.   TextArray[tindex] := C;
  404.   tindex := tindex+1; column := column+1;
  405.   end
  406. else
  407.   begin
  408.   WriteLn('Object Code Overflow!');
  409.   Halt(1);
  410.   end;
  411. end;
  412.  
  413. {-------------InsertStr}
  414. PROCEDURE InsertStr(S : bigstring);
  415. var I : Integer;
  416. begin
  417. for I := 1 to Ord(S[0]) do InsertChr(S[I]);
  418. end;
  419.  
  420. {-------------Hex2}
  421. FUNCTION Hex2(B : Byte) : string4;
  422. const hexdigs : array[0..15] of Char = '0123456789ABCDEF';
  423. var bz : Byte;
  424. begin
  425. bz := B and $f; B := B shr 4;
  426. Hex2 := hexdigs[B]+hexdigs[bz];
  427. end;
  428.  
  429. {-------------Hex4}
  430. FUNCTION Hex4(W : Integer) : string4;
  431. begin Hex4 := Hex2(Lo(W))+Hex2(Hi(W)); end;
  432.  
  433. {-------------InsertByte}
  434. PROCEDURE InsertByte(B : Byte);
  435. begin
  436. if not str_start then InsertChr('/');
  437. InsertStr('$'+Hex2(B));
  438. ByteCount := ByteCount+1;
  439. str_start := False;
  440. Wait_Already:=False;  {any byte inserted cancels a WAIT}
  441. end;
  442.  
  443. {-------------InsertWord}
  444. PROCEDURE InsertWord(W : Integer);
  445. begin
  446. InsertByte(Lo(W)); InsertByte(Hi(W));
  447. end;
  448.  
  449. {-------------InsertHi_Low}
  450. PROCEDURE InsertHi_Low(W : Integer);
  451.   {insert a word in reverse order}
  452. begin
  453. InsertByte(Hi(W)); InsertByte(Lo(W));
  454. end;
  455.  
  456. {-------------InsertWait}
  457. PROCEDURE InsertWait;
  458. begin  {Insert a 'WAIT' for Fl Pt only if none already input}
  459. if not Wait_Already then InsertByte($9B);
  460. end;
  461.  
  462. {-------------modify_byte}
  463. PROCEDURE modify_byte(I : Integer; modify : Byte);
  464.   {Modify an ascii byte string in textarray by adding modify to its value}
  465. var
  466.   st : string4;
  467.   J : Integer;
  468.  
  469.   FUNCTION hextobyte(I : Integer; var J : Integer) : Byte;
  470.     {Starting at tindex, i, convert hex to a byte. return j, the tindex where
  471.      byte started}
  472.   var
  473.     result, tmp : Byte;
  474.     K : integer;
  475.     C : Char;
  476.   const hex : set of Char = ['0'..'9', 'A'..'F'];
  477.   begin
  478.   result := 0;
  479.   while not(TextArray[I] in hex) do I := I+1; {skip '/' and '$'}
  480.   J := I;
  481.   for K:=I to I+1 do
  482.     begin
  483.     C := TextArray[K];
  484.     if C <= '9' then tmp := Ord(C)-Ord('0') else tmp := Ord(C)-Ord('A')+10;
  485.     result := (result shl 4)+tmp;
  486.     end;
  487.   hextobyte := result;
  488.   end;
  489.  
  490. begin
  491. st := Hex2(hextobyte(I, J)+modify);
  492. TextArray[J] := st[1];
  493. TextArray[J+1] := st[2];
  494. end;
  495.  
  496. {-------------DoNext}
  497. PROCEDURE DoNext;
  498. var tmpch : Char;
  499.  
  500. begin
  501. OldChi := Chi;
  502. symbol := False;
  503. if sym = EOLsym then Exit;  {do nothing}
  504. skipspaces;                 {note commas are significant}
  505. if (Uch = Chr(cr)) or (Uch = ';') then sym := EOLsym
  506. else if Uch = ',' then begin sym := comma; GetCh; end
  507. else if (Uch = '>') or (Uch = '<') then
  508.   begin
  509.   tmpch := Uch; GetCh;
  510.   if not getsymbol(symname) then Error(Chi, 'Symbol Name Exp');
  511.   if tmpch = '<' then sym := disp8 else sym := disp16;
  512.   symbol := True;           {disp8/16 is a symbol}
  513.   end
  514. else if getaddress then
  515.   begin
  516.   if NoAddrs then errnull
  517.   else sym := address;
  518.   end
  519. else if getexpr(nvalue) then
  520.   begin
  521.   if bytesize(nvalue) then
  522.     sym := disp8 else sym := disp16;
  523.   end
  524. else if (Uch >= 'A') and (Uch <= 'Z') then
  525.   begin getstring; symname := Lsid;
  526.   if (Lsid = 'FAR') or (Lsid = 'NEAR') or (Lsid = 'SHORT') then
  527.     sym := jmpdist
  528.   else if Lsid = 'ST' then sym := STsym
  529.   else sym := identifier;
  530.   end
  531. else if Uch = '+' then begin sym := plus; GetCh; end
  532. else if Uch = '[' then begin sym := lfbrack; GetCh; end
  533. else if Uch = ']' then begin sym := rtbrack; GetCh; end
  534. else begin sym := othersym; GetCh; end;
  535. end;
  536.  
  537. {-------------NextA}
  538. PROCEDURE NextA;            {Get the next item but also process any
  539.                             'WORD' 'BYTE', 'DWORD', 'QWORD',etc 'PTR'}
  540. type sizeary = array[0..4] of string[2];
  541. var tmp : ptrtype;
  542.   indx : Integer;
  543. const ptrary : sizeary = ('BY', 'WO', 'DW', 'QW', 'TB');
  544.       ptrary1 : array[0..4] of string[5] =
  545.                   ('BYTE','WORD','DWORD','QWORD','TBYTE');
  546.  
  547. begin
  548. DoNext;
  549. if sym = identifier then
  550.   begin
  551.   tmp := bptr; indx := 0;
  552.   while (tmp < unkptr) and (Lsid <> ptrary[indx]) and (Lsid <>ptrary1[indx]) do
  553.     begin
  554.     tmp := Succ(tmp); indx := indx+1;
  555.     end;
  556.   if tmp < unkptr then
  557.     begin ByWord := tmp; DoNext; end;
  558.   if Str = 'PTR  ' then DoNext; {ignore 'PTR'}
  559.   end;
  560. end;
  561.  
  562. {-------------displace_bytes}
  563. PROCEDURE displace_bytes(W : Integer);
  564. var C : Char;
  565. begin
  566. if displace then
  567.   with SaveOfs do
  568.     if symb then
  569.       begin                 {displacement is a symbol}
  570.       if W = 1 then C := '>' else C := '<';
  571.       InsertStr('/'+C+sname);
  572.       if value <> 0 then    {Add it in too, don't reverse bytes}
  573.         InsertStr('+$'+Hex2(Hi(value))+Hex2(Lo(value)));
  574.       if W = 1 then ByteCount := ByteCount+2 else ByteCount := ByteCount+1;
  575.       end
  576.     else begin
  577.     if W = 1 then InsertWord(value) else InsertByte(Lo(value));
  578.     end;
  579. end;
  580.  
  581. {-------------data_bytes}
  582. PROCEDURE data_bytes(word : Boolean);
  583. var C : Char;
  584. begin
  585. with DataVal do
  586.   if symb then
  587.     begin                   {data is a symbol}
  588.     if word then C := '>' else C := '<';
  589.     InsertStr('/'+C+sname);
  590.     if value <> 0 then      {add it in too}
  591.       InsertStr('+$'+Hex2(Hi(value))+Hex2(Lo(value)));
  592.     if word then ByteCount := ByteCount+2 else ByteCount := ByteCount+1;
  593.     end
  594.   else begin
  595.   if word then InsertWord(value) else InsertByte(Lo(value));
  596.   end;
  597. end;
  598.  
  599. {-------------GetIR}
  600. FUNCTION GetIR : Boolean;
  601. var reg : indxreg;
  602. begin
  603. GetIR := False; reg := none;
  604. if (sym = identifier) and (Lsid[0] = Chr(2)) then
  605.   if id2 = 'BX' then reg := bx
  606.   else if id2 = 'SI' then reg := si
  607.   else if id2 = 'DI' then reg := di
  608.   else if id2 = 'BP' then reg := bp;
  609. if reg <> none then
  610.   begin
  611.   irset := irset+[reg];
  612.   GetIR := True;
  613.   NextA;
  614.   end;
  615. end;
  616.  
  617. {-------------MemReg}
  618. FUNCTION MemReg(var W : Integer) : Boolean;
  619. label 10;
  620.  
  621.   {Does not handle the 'reg' part of the mem/reg. Returns disp true if
  622.   a displacement is found with w=0 for byte disp and w=1 for word
  623.   disp.  Any displacement is output in saveofs.}
  624.  
  625. var
  626.   SaveChi : Integer;
  627.   dsp16, oldaddrs, result_MemReg : Boolean;
  628. begin
  629. SaveChi := OldChi; dsp16 := False;
  630. result_MemReg := False;
  631. oldaddrs := NoAddrs; NoAddrs := True;
  632. SaveOfs.value := 0; SaveOfs.symb := False; irset := [];
  633. while (sym <> comma) and (sym <> EOLsym) do {',' or cr terminate a MemReg}
  634.   begin
  635.   if sym = lfbrack then
  636.     begin result_MemReg := True; NextA; end;
  637.   if sym = plus then NextA;
  638.   if (sym = disp8) or (sym = disp16) then
  639.     with SaveOfs do
  640.       begin
  641.       dsp16 := dsp16 or (sym = disp16);
  642.       if symbol then
  643.         begin
  644.         symb := True; sname := symname;
  645.         end
  646.       else value := value+nvalue;
  647.       NextA;
  648.       end
  649.   else if not GetIR then
  650.     if sym = rtbrack then NextA
  651.     else if result_MemReg then
  652.       begin Error(Chi, 'Comma or Line End Exp'); NextA; end
  653.     else goto 10;           {abort}
  654.   end;
  655. if result_MemReg then
  656.   begin                     {at least one '[' found}
  657.   if (irset = []) or (irset = [bp]) then rmm := 6
  658.   else if irset = [bx, si] then rmm := 0
  659.   else if irset = [bx, di] then rmm := 1
  660.   else if irset = [bp, si] then rmm := 2
  661.   else if irset = [bp, di] then rmm := 3
  662.   else if irset = [si] then rmm := 4
  663.   else if irset = [di] then rmm := 5
  664.   else if irset = [bx] then rmm := 7
  665.   else Error(Chi, 'Bad Register Combination');
  666.  
  667.   NextA;                    {pass over any commas}
  668.   with SaveOfs do
  669.     dsp16 := dsp16 or (symb and (value <> 0)) or not bytesize(value);
  670.   if irset = [] then
  671.     begin displace := True; md := 0; W := 1; end {direct address}
  672.   else if (irset = [bp]) and not dsp16 then
  673.     begin displace := True; md := 1; W := 0; end {bp must have displ}
  674.   else if (SaveOfs.value = 0) and not SaveOfs.symb then
  675.     begin displace := False; md := 0; W := 3; end
  676.   else if not dsp16 then    {8 bit}
  677.     begin displace := True; md := 1; W := 0; end
  678.   else begin displace := True; md := 2; W := 1; end;
  679.   modebyt := 64*md+rmm;
  680.   end
  681. else
  682. 10: begin                     {not a MemReg}
  683.   Chi := SaveChi-1; GetCh;  {restore as in beginning}
  684.   NextA;
  685.   end;
  686. NoAddrs := oldaddrs;
  687. MemReg := result_MemReg;
  688. end;
  689.  
  690. {-------------st_st}
  691. FUNCTION st_st : Boolean;   {pick up st,st(i) or st(i),st or just st(i)}
  692. var err, rslt : Boolean;
  693.  
  694.   FUNCTION getsti_val : Boolean;
  695.   var grslt : Boolean;
  696.   begin
  697.   NextA;
  698.   grslt := sym = disp8;
  699.   if grslt then
  700.     begin
  701.     sti_val := nvalue;
  702.     err := ((sti_val and $f8) <> 0); {check limit of 7}
  703.     NextA;
  704.     end;
  705.   getsti_val := grslt;
  706.   end;
  707.  
  708. begin
  709. err := False;
  710. rslt := sym = STsym;
  711. if rslt then
  712.   begin
  713.   if getsti_val then
  714.     begin
  715.     st_first := False;      {st(i) is first}
  716.     while (sym = comma) or (sym = STsym) do NextA;
  717.     end
  718.   else
  719.     begin
  720.     st_first := True;       {st preceeds st(i)}
  721.     if sym = comma then NextA;
  722.     if sym = STsym then
  723.       begin
  724.       if not getsti_val then
  725.         err := True;
  726.       end
  727.     else err := True;
  728.     end;
  729.   if err then errnull;
  730.   end;
  731. st_st := rslt;
  732. end;
  733.  
  734. {-------------fstionly}
  735. FUNCTION fstionly : Boolean;
  736.   {Fl Pt instructions having only one form using st(i) operand}
  737.   {faddp,fmulp,fsubp,fsubrp,fdivp,fdivrp,ffree,fxch -- 0..7 }
  738. type arraytype = array[0..7] of Integer;
  739.   table = array[0..7, 0..5] of Char;
  740. var indx : Integer;
  741.   rslt : Boolean;
  742. const
  743.   stiary : arraytype =
  744.        ($dec0, $dec8, $dee8, $dee0, $def8, $def0, $ddc0, $d9c8);
  745.   stionlytable : table = ('FADDP ', 'FMULP ', 'FSUBP ',
  746.        'FSUBRP', 'FDIVP ', 'FDIVRP', 'FFREE ', 'FXCH  ');
  747.  
  748. begin
  749. rslt := matchlst(stionlytable, 6, 7, indx);
  750. if rslt then
  751.   begin
  752.   NextA;
  753.   if not st_st then
  754.     begin
  755.     if sym = EOLsym then sti_val := 1
  756.     else errincorrect;
  757.     end;
  758.   InsertWait;
  759.   InsertHi_Low(stiary[indx]+sti_val);
  760.   end;
  761. fstionly := rslt;
  762. end;
  763.  
  764. {-------------fmemonly}
  765. FUNCTION fmemonly : Boolean;
  766.   {Fl Pt instructions having only one form using a memory operand}
  767.   {fldenv,fldcw,fstenv,fstcw,fbstp,fbld,frstor,fsave,fstsw,
  768.   fnsave,fnstcw,fnstenv,fnstsw--0..12 }
  769. type arraytype = array[0..12] of Integer;
  770.   table = array[0..12, 0..6] of Char;
  771. var indx : Integer;
  772.   rslt : Boolean;
  773. const
  774.   memary : arraytype = (
  775.     $d920, $d928, $d930, $d938, $df30, $df20, $dd20, $dd30, $dd38,
  776.     $dd30, $d938, $d930, $dd38);
  777.   memonlytable : table =
  778.    ('FLDENV ', 'FLDCW  ', 'FSTENV ', 'FSTCW  ', 'FBSTP  ', 'FBLD   ',
  779.     'FRSTOR ', 'FSAVE  ', 'FSTSW  ',
  780.     'FNSAVE ', 'FNSTCW ', 'FNSTENV', 'FNSTSW ');
  781. begin
  782. rslt := matchlst(memonlytable, 7, 12, indx);
  783. if rslt then
  784.   begin
  785.   NextA;
  786.   if indx < 9 then InsertWait; {fwait}
  787.   if MemReg(w1) then
  788.     begin
  789.     InsertHi_Low(memary[indx]+modebyt);
  790.     displace_bytes(w1);
  791.     end
  792.   else errincorrect;
  793.   end;
  794. fmemonly := rslt;
  795. end;
  796.  
  797. {-------------fldtype}
  798. FUNCTION fldtype : Boolean;
  799.   {Do fld,fst,fstp-- 0..2}
  800. type
  801.   arraytype = array[0..2, dwptr..unkptr] of Integer;
  802.   table = array[0..2, 0..3] of Char;
  803. var indx, tmp : Integer;
  804.   rslt : Boolean;
  805. const
  806.   fldarray : arraytype = (
  807.     ($d900, $dd00, $db28, $d9c0),
  808.     ($d910, $dd10, 0, $ddd0),
  809.     ($d918, $dd18, $db38, $ddd8));
  810.   fldtable : table = ('FLD ', 'FST ', 'FSTP');
  811. begin
  812. rslt := matchlst(fldtable, 4, 2, indx);
  813. if rslt then
  814.   begin
  815.   NextA;
  816.   InsertWait;           {fwait}
  817.   if ByWord >= dwptr then
  818.     tmp := fldarray[indx, ByWord];
  819.   if MemReg(w1) then
  820.     begin
  821.     if (ByWord >= dwptr) and (ByWord <= tbptr) then
  822.       begin
  823.       InsertHi_Low(tmp+modebyt);
  824.       displace_bytes(w1);
  825.       if tmp = 0 then Error(Chi, 'TBYTE not Permitted');
  826.       end
  827.     else Error(Chi, 'DWORD, QWORD, or TBYTE Req''d');
  828.     end
  829.   else if st_st then
  830.     InsertHi_Low(tmp+sti_val)
  831.   else errincorrect;
  832.   end;
  833. fldtype := rslt;
  834. end;
  835.  
  836. {-------------fildtype}
  837. FUNCTION fildtype : Boolean;
  838.   {do fild,fist,fistp-- 0..2}
  839. type
  840.   arraytype = array[0..2, wptr..qwptr] of Integer;
  841.   table = array[0..2, 0..4] of Char;
  842. var indx, tmp : Integer;
  843.   rslt : Boolean;
  844. const
  845.   fildarray : arraytype = (
  846.     ($df00, $db00, $df28),
  847.     ($df10, $db10, 0),
  848.     ($df18, $db18, $df38));
  849.   fildtable : table = ('FILD ', 'FIST ', 'FISTP');
  850. begin
  851. rslt := matchlst(fildtable, 5, 2, indx);
  852. if rslt then
  853.   begin
  854.   NextA;
  855.   if MemReg(w1) then
  856.     begin
  857.     if (ByWord >= wptr) and (ByWord <= qwptr) then
  858.       begin
  859.       InsertWait;       {fwait}
  860.       tmp := fildarray[indx, ByWord];
  861.       InsertHi_Low(tmp+modebyt);
  862.       displace_bytes(w1);
  863.       if tmp = 0 then Error(Chi, 'QWORD not Permitted');
  864.       end
  865.     else Error(Chi, 'WORD, DWORD, or QWORD Req''d');
  866.     end
  867.   else errincorrect;
  868.   end;
  869. fildtype := rslt;
  870. end;
  871.  
  872. {-------------faddtype}
  873. FUNCTION faddtype : Boolean;
  874.   {The fadd,fmul,fcom,fcomp,fsub,fsubr,fdiv,fdivr instructions}
  875. var indx : Integer;
  876.   rslt : Boolean;
  877. type table = array[0..7, 0..4] of Char;
  878. const faddtable : table = ('FADD ', 'FMUL ', 'FCOM ', 'FCOMP',
  879.   'FSUB ', 'FSUBR', 'FDIV ', 'FDIVR');
  880. begin
  881. rslt := False;
  882. if matchlst(faddtable, 5, 7, indx) then
  883.   begin
  884.   NoAddrs := True;
  885.   rslt := True;
  886.   NextA;
  887.   InsertWait;           {fwait}
  888.   if MemReg(w1) then
  889.     begin
  890.     if ByWord = dwptr then InsertByte($d8)
  891.     else if ByWord = qwptr then InsertByte($dc)
  892.     else Error(Chi, 'DWORD or QWORD Req''d');
  893.     InsertByte(modebyt+8*indx);
  894.     displace_bytes(w1);
  895.     end
  896.   else if st_st then        {Must be st,st(i) or st(i),st }
  897.     begin
  898.     if st_first or (indx = 2 {fcom} ) or (indx = 3 {fcomp} ) then
  899.     InsertByte($d8) else InsertByte($dc);
  900.     modebyt := $c0+8*indx+sti_val;
  901.     if not st_first and (indx >= 6 {fdiv} ) then
  902.       modebyt := modebyt xor 8; {reverse fdiv,fdivr for not st_first}
  903.     InsertByte(modebyt);
  904.     end
  905.   else errincorrect;
  906.   end;
  907. faddtype := rslt;
  908. end;
  909.  
  910. {-------------fiaddtype}
  911. FUNCTION fiaddtype : Boolean;
  912.   {the fiadd,fimul,ficom,ficomp,fisub,fisubr,fidiv,fidivr instructions}
  913. type table = array[0..7, 0..5] of Char;
  914. var indx : Integer;
  915.   rslt : Boolean;
  916. const fiaddtable : table = ('FIADD ', 'FIMUL ', 'FICOM ', 'FICOMP',
  917.   'FISUB ', 'FISUBR', 'FIDIV ', 'FIDIVR');
  918. begin
  919. rslt := False;
  920. if matchlst(fiaddtable, 6, 7, indx) then
  921.   begin
  922.   NoAddrs := True;
  923.   rslt := True;
  924.   NextA;
  925.   if MemReg(w1) then
  926.     begin
  927.     InsertWait;         {fwait}
  928.     if ByWord = dwptr then InsertByte($da)
  929.     else if ByWord = wptr then InsertByte($de)
  930.     else Error(Chi, 'WORD or DWORD Req''d');
  931.     InsertByte(modebyt+8*indx);
  932.     displace_bytes(w1);
  933.     end
  934.   else errincorrect;
  935.   end;
  936. fiaddtype := rslt;
  937. end;
  938.  
  939. {-------------fnoperand}
  940. FUNCTION fnoperand : Boolean;
  941.   {do the Fl Pt no operand instructions}
  942. type table = array[0..32, 0..6] of Char;
  943. var indx : Integer;
  944.   rslt : Boolean;
  945. const
  946.   fnoptable : table =       {Ordered with fnopcode}
  947.    ('FNOP   ', 'FCHS   ', 'FABS   ', 'FTST   ', 'FXAM   ',
  948.     'FLD1   ', 'FLDL2T ', 'FLDL2E ', 'FLDPI  ', 'FLDLG2 ', 'FLDLN2 ',
  949.     'FLDZ   ', 'F2XM1  ', 'FYL2X  ', 'FPTAN  ', 'FPATAN ', 'FXTRACT',
  950.     'FDECSTP', 'FINCSTP', 'FPREM  ', 'FYL2XP1', 'FSQRT  ', 'FRNDINT',
  951.     'FSCALE ', 'FENI   ', 'FDISI  ', 'FCLEX  ', 'FINIT  ', 'FCOMPP ',
  952.     'FNCLEX ', 'FNDISI ', 'FNENI  ', 'FNINIT ');
  953.  
  954.   fnopcode : array[0..32] of Integer =
  955.    ($d9d0, $d9e0, $d9e1, $d9e4, $d9e5, $d9e8,
  956.     $d9e9, $d9ea, $d9eb, $d9ec, $d9ed, $d9ee,
  957.     $d9f0, $d9f1, $d9f2, $d9f3, $d9f4, $d9f6,
  958.     $d9f7, $d9f8, $d9f9, $d9fa, $d9fc, $d9fd,
  959.     $dbe0, $dbe1, $dbe2, $dbe3, $ded9,
  960.     $dbe2, $dbe1, $dbe0, $dbe3);
  961.  
  962. begin
  963. rslt := matchlst(fnoptable, 7, 32, indx);
  964. if rslt then
  965.   begin
  966.   NextA;
  967.   if indx < 29 then InsertWait; {fwait}
  968.   InsertHi_Low(fnopcode[indx]);
  969.   end;
  970. fnoperand := rslt;
  971. end;
  972.  
  973. {-------------register}
  974. FUNCTION register(var R, W : Integer) : Boolean;
  975. type
  976.   regarytype = array[0..15] of array[1..2] of Char;
  977. const regarray : regarytype = (
  978.   'AL', 'CL', 'DL', 'BL', 'AH', 'CH', 'DH', 'BH',
  979.   'AX', 'CX', 'DX', 'BX', 'SP', 'BP', 'SI', 'DI');
  980. var result_reg : Boolean;
  981. begin
  982. result_reg := False;
  983. if (Lsid[0] = Chr(2)) and (sym = identifier) then
  984.   begin
  985.   R := $ffff;
  986.   repeat
  987.     R := R+1;
  988.   until (R > 15) or (id2 = regarray[R]);
  989.   result_reg := R <= 15;
  990.   if result_reg then
  991.     begin
  992.     NextA;
  993.     if sym = comma then NextA;
  994.     end;
  995.   W := R div 8;             {w=1 for word type register}
  996.   R := R and 7;
  997.   end;
  998. register := result_reg;
  999. end;
  1000.  
  1001. {-------------segregister}
  1002. FUNCTION segregister(var R : Integer) : Boolean;
  1003. var result_segr : Boolean;
  1004. begin
  1005. if (sym = identifier) and (Lsid[0] = Chr(2)) then
  1006.   begin
  1007.   result_segr := True;
  1008.   if id2 = 'ES' then R := 0
  1009.   else if id2 = 'CS' then R := 1
  1010.   else if id2 = 'SS' then R := 2
  1011.   else if id2 = 'DS' then R := 3
  1012.   else result_segr := False;
  1013.   if result_segr then
  1014.     begin
  1015.     NextA;
  1016.     if sym = comma then NextA;
  1017.     end;
  1018.   end
  1019. else result_segr := False;
  1020. segregister := result_segr;
  1021. end;
  1022.  
  1023. {-------------Data}
  1024. FUNCTION Data(var wd : Boolean) : Boolean;
  1025.   {See if immediate data is present.  Set wd if data found is word size}
  1026. var SaveChi : Integer;
  1027.   result : Boolean;
  1028. begin
  1029. result := False; wd := False;
  1030. SaveChi := OldChi;
  1031. with DataVal do
  1032.   begin
  1033.   value := 0; symb := False;
  1034.   while (sym = disp8) or (sym = disp16) do
  1035.     begin
  1036.     result := True;
  1037.     if symbol then
  1038.       begin
  1039.       wd := wd or (sym = disp16);
  1040.       symb := True;
  1041.       sname := symname;
  1042.       end
  1043.     else value := value+nvalue;
  1044.     NextA; if sym = plus then NextA;
  1045.     end;
  1046.   result := (sym = EOLsym) and result;
  1047.   wd := wd or not bytesize(value);
  1048.   end;
  1049. Data := result;
  1050. if not result then
  1051.   begin
  1052.   Chi := SaveChi-1; GetCh; NextA;
  1053.   end;
  1054. end;
  1055.  
  1056. {-------------TwoOperands}
  1057. FUNCTION TwoOperands : Boolean;
  1058.   {Handles codes with two operands}
  1059. label 2;
  1060. type instype = (mov, adc, addx, andx, cmp, orx, sbb, sub, xorx, test, xchg,
  1061.   lds, les, lea);
  1062.   nametype = array[mov..lea] of array[1..5] of Char;
  1063.   codetype = array[mov..lea] of Byte;
  1064.   shcodetype = array[mov..test] of Byte;
  1065. var inst : instype;
  1066.   tmp : Byte;
  1067.  
  1068. const instname : nametype = (
  1069.   'MOV  ', 'ADC  ', 'ADD  ', 'AND  ', 'CMP  ', 'OR   ',
  1070.   'SBB  ', 'SUB  ', 'XOR  ', 'TEST ', 'XCHG ', 'LDS  ',
  1071.   'LES  ', 'LEA  ');
  1072.  
  1073.   immedop : codetype = ($c6, $80, $80, $80, $80, $80, $80, $80, $80, $f6, 0,
  1074.     0, 0, 0);
  1075.   immedreg : codetype = (0, $10, 0, $20, $38, 8, $18, $28, $30, 0, 0,
  1076.     0, 0, 0);
  1077.   memregop : codetype = ($88, $10, 0, $20, $38, 8, $18, $28, $30, $84, $86,
  1078.     $c5, $c4, $8d);
  1079.   shimmedop : shcodetype = (0, $14, 4, $24, $3c, $c, $1c, $2c, $34, $a8);
  1080.  
  1081. begin TwoOperands := False;
  1082. for inst := mov to lea do
  1083.   if Str = instname[inst] then
  1084.     goto 2;
  1085. Exit;                         {not found}
  1086. 2:                            {found}
  1087. NoAddrs := True;            {full address not acceptable}
  1088. TwoOperands := True;
  1089. NextA;
  1090. if register(reg1, w1) then
  1091.   begin
  1092.   if register(reg2, w2) then
  1093.     begin                   {mov reg,reg}
  1094.     if inst >= lds then Error(Chi, 'Register not Permitted');
  1095.     if w1 <> w2 then Error(Chi, 'Registers Incompatible');
  1096.     if (inst = xchg) and ((w1 = 1) and ((reg1 = 0) or (reg2 = 0))) then
  1097.       InsertByte($90+reg1+reg2)
  1098.     else
  1099.       begin
  1100.       InsertByte(memregop[inst]+w1);
  1101.       InsertByte($c0+reg1+8*reg2);
  1102.       end;
  1103.     end
  1104.   else if segregister(reg2) then
  1105.     begin                   {mov reg,segreg}
  1106.     if (w1 = 0) or (inst <> mov) then segmerr;
  1107.     InsertByte($8c); InsertByte($c0+8*reg2+reg1);
  1108.     end
  1109.   else if Data(wordd) then
  1110.     begin                   {mov reg,data}
  1111.     signext := 0;           {signext not presently in use}
  1112.     if inst >= xchg then Error(Chi, 'Immediate not Permitted');
  1113.     if (Ord(wordd) > w1) then datalarge;
  1114.     if (inst = mov) then
  1115.       begin
  1116.       InsertByte($b0+8*w1+reg1);
  1117.       end
  1118.     else
  1119.       if (reg1 = 0) {ax or al} then
  1120.         InsertByte(shimmedop[inst]+w1) {add ac,immed}
  1121.       else
  1122.         begin
  1123.         (*       if (inst<>test) and (w1=1) and bits_7 then
  1124.         signext:=2;         {the sign extension bit}     *)
  1125.         InsertByte(immedop[inst]+w1+signext);
  1126.         InsertByte($c0+immedreg[inst]+reg1);
  1127.         end;
  1128.     (*    Insertbyte(lo(dataval));
  1129.     if (w1>0) and (signext=0) then Insertbyte(hi(dataval));   *)
  1130.     data_bytes(w1 > 0);     {output the immediate data}
  1131.     end
  1132.   else if MemReg(w2) then
  1133.     begin                   {mov reg,mem/reg}
  1134.     if (inst = mov) and (reg1 = 0) {ax or al} and (rmm = 6) and (md = 0) then
  1135.       begin                 {mov ac,mem}
  1136.       InsertByte($a0+w1);
  1137.       end
  1138.     else
  1139.       begin
  1140.       tmp := memregop[inst];
  1141.       if inst <= xchg then
  1142.         begin
  1143.         tmp := tmp+w1;
  1144.         if inst <> test then tmp := tmp or 2; {to,from bit}
  1145.         end;
  1146.       InsertByte(tmp);
  1147.       InsertByte(modebyt+8*reg1);
  1148.       end;
  1149.     displace_bytes(w2);     {add on any displacement bytes}
  1150.     end
  1151.   else errnull;
  1152.   end
  1153. else if segregister(reg1) then
  1154.   begin
  1155.   if inst <> mov then segmerr;
  1156.   InsertByte($8e);
  1157.   if register(reg2, w2) then
  1158.     begin                   {mov segreg,reg}
  1159.     if (w2 = 0) then wordreg;
  1160.     InsertByte($c0+8*reg1+reg2);
  1161.     end
  1162.   else if MemReg(w2) then
  1163.     begin                   {mov segreg,mem/reg}
  1164.     InsertByte(modebyt+8*reg1);
  1165.     displace_bytes(w2);     {add any displacement bytes}
  1166.     end
  1167.   else errnull;
  1168.   end
  1169. else if MemReg(w1) and (inst <= xchg) then
  1170.   begin
  1171.   if register(reg2, w2) then
  1172.     begin                   {mov mem/reg,reg}
  1173.     if (w2 > Ord(ByWord)) then Error(Chi, 'Byte Reg Exp');
  1174.     if (inst = mov) and (reg2 = 0) {ax or al} and (rmm = 6) and (md = 0) then
  1175.       begin                 {mov ac, mem}
  1176.       InsertByte($a2+w2);
  1177.       end
  1178.     else
  1179.       begin
  1180.       InsertByte(memregop[inst]+w2);
  1181.       InsertByte(modebyt+8*reg2);
  1182.       end;
  1183.     displace_bytes(w1);
  1184.     end
  1185.   else if segregister(reg2) then
  1186.     begin                   {mov mem/reg,segreg}
  1187.     if (inst <> mov) then segmerr;
  1188.     InsertByte($8c); InsertByte(modebyt+8*reg2);
  1189.     displace_bytes(w1);
  1190.     end
  1191.   else if (Data(wordd)) and (inst < xchg) then
  1192.     begin                   {mov mem/reg, data}
  1193.     chk_bwptr;
  1194.     if (Ord(wordd) > Ord(ByWord)) then datalarge;
  1195.     (*     if (inst>=adc) and (inst<=xorx) and (byword=wptr) and bits_7 then
  1196.     signext:=2 else *) signext := 0; {the sign extension bit,
  1197.                                        not currently used}
  1198.     InsertByte(immedop[inst]+Ord(ByWord)+signext);
  1199.     InsertByte(modebyt+immedreg[inst]);
  1200.     displace_bytes(w1);     {add displacement bytes}
  1201.     (*     Insertbyte(lo(dataval));
  1202.     if (byword=wptr) and (signext=0) then Insertbyte(hi(dataval));  *)
  1203.     data_bytes(ByWord = wptr); {the immediate data}
  1204.     end
  1205.   else errnull;
  1206.   end
  1207. else if (sym = disp8) or (sym = disp16) then
  1208.   Error(Chi, 'Immediate not Permitted')
  1209. else errnull;
  1210. end;
  1211.  
  1212. {-------------OneOperand}
  1213. FUNCTION OneOperand : Boolean;
  1214.   {Handles codes with one operand}
  1215. type instype = (dec, inc, push, pop, nott, Neg);
  1216.   nametype = array[dec..Neg] of array[1..5] of Char;
  1217.   codetype = array[dec..Neg] of Byte;
  1218. var inst : instype;
  1219.   pushpop : Boolean;
  1220.  
  1221. const
  1222.   instname : nametype = (
  1223.      'DEC  ', 'INC  ', 'PUSH ', 'POP  ', 'NOT  ', 'NEG  ');
  1224.  
  1225.   regop : codetype = ($48, $40, $50, $58, 0, 0);
  1226.   segregop : codetype = (0, 0, 6, 7, 0, 0);
  1227.   memregop : codetype = ($fe, $fe, $ff, $8f, $f6, $f6);
  1228.   memregcode : codetype = ($8, 0, $30, 0, $10, $18);
  1229.  
  1230. begin OneOperand := False;
  1231. for inst := dec to Neg do
  1232.   if Str = instname[inst] then
  1233.     begin
  1234.     pushpop := (inst = push) or (inst = pop);
  1235.     NoAddrs := True;
  1236.     OneOperand := True;
  1237.     NextA;
  1238.     if register(reg1, w1) then
  1239.       begin
  1240.       if (w1 = 1) and (inst < nott) then
  1241.         begin               {16 bit register instructions}
  1242.         InsertByte(regop[inst]+reg1);
  1243.         end
  1244.       else begin            {byte register or neg,not with any reg}
  1245.       InsertByte(memregop[inst]+w1);
  1246.       InsertByte($c0+memregcode[inst]+reg1);
  1247.       if pushpop then
  1248.         wordreg;
  1249.       end
  1250.       end                   {if reg}
  1251.     else if segregister(reg1) then
  1252.       begin                 {segment reg--push,pop only}
  1253.       InsertByte(segregop[inst]+8*reg1);
  1254.       if not pushpop then segmerr
  1255.       end
  1256.     else if MemReg(w1) then
  1257.       begin                 {memreg  (not register)}
  1258.       if not pushpop then chk_bwptr;
  1259.       InsertByte(memregop[inst] or Ord(ByWord));
  1260.       InsertByte(modebyt+memregcode[inst]);
  1261.       displace_bytes(w1);
  1262.       end
  1263.     else errincorrect;
  1264.     end;                    {if st}
  1265. end;
  1266.  
  1267. {-------------NoOperand}
  1268. FUNCTION NoOperand : Boolean;
  1269.   {Those instructions consisting only of opcode}
  1270. const nmbsop = 31;
  1271. type sofield = array[0..nmbsop] of array[1..5] of Char;
  1272.   opfield = array[0..nmbsop] of Byte;
  1273. var index : Integer;
  1274. const
  1275.   sop : sofield = (
  1276.     'DAA  ', 'AAA  ', 'NOP  ', 'MOVSB', 'MOVSW', 'CMPSB', 'CMPSW',
  1277.     'XLAT ', 'HLT  ',
  1278.     'CMC  ', 'DAS  ', 'AAS  ', 'CBW  ', 'CWD  ', 'PUSHF',
  1279.     'POPF ', 'SAHF ', 'LAHF ', 'STOSB', 'STOSW', 'LODSB', 'LODSW',
  1280.     'SCASB', 'SCASW', 'INTO ', 'IRET ', 'CLC  ', 'STC  ', 'CLI  ',
  1281.     'STI  ', 'CLD  ', 'STD  ');
  1282.   opcode : opfield = (
  1283.     $27, $37, $90, $a4, $a5, $a6, $a7, $d7, $f4,
  1284.     $f5, $2f, $3f, $98, $99, $9c, $9d, $9e, $9f, $aa, $ab, $ac, $ad,
  1285.     $ae, $af, $ce, $cf, $f8, $f9, $fa, $fb, $fc, $fd);
  1286.  
  1287. begin NoOperand := False;
  1288. for index := 0 to nmbsop do
  1289.   if Str = sop[index] then
  1290.     begin
  1291.     InsertByte(opcode[index]);
  1292.     NoOperand := True;
  1293.     NextA;
  1294.     Exit;
  1295.     end;
  1296. end;
  1297.  
  1298. {-------------prefix}
  1299. FUNCTION prefix : Boolean;
  1300.   {process the prefix instructions}
  1301. const nmbsop = 11;
  1302. type field = array[0..nmbsop] of string5;
  1303.   opfield = array[0..nmbsop] of Byte;
  1304. var index : Integer;
  1305.     SaveWait : boolean;
  1306.     opc : byte;
  1307. const
  1308.   ops : field = (
  1309.     'LOCK ', 'REP  ', 'REPZ ',
  1310.     'REPNZ', 'REPE ', 'REPNE', 'WAIT ', 'FWAIT',
  1311.     'ES   ', 'DS   ', 'CS   ', 'SS   ');
  1312.   opcode : opfield = (
  1313.     $f0, $f2, $f3, $f2, $f3, $f2, $9b, $9b, $26, $3e, $2e, $36);
  1314.  
  1315. begin prefix := False;
  1316. for index := 0 to nmbsop do
  1317.   if Str = ops[index] then
  1318.     begin
  1319.     opc:=opcode[index];
  1320.     SaveWait := Wait_Already;  {save any WAIT already programed}
  1321.     InsertByte(opc);
  1322.     Wait_Already:=SaveWait or (opc=$9B); {set for WAIT or FWAIT}
  1323.     tindex0 := tindex;      {for future fix ups}
  1324.     if Uch = ':' then GetCh; {es: etc permitted with a colon}
  1325.     prefix := True;
  1326.     Exit;
  1327.     end;
  1328. end;
  1329.  
  1330. {-------------FindLabel}
  1331. FUNCTION FindLabel(var B : Integer) : Boolean;
  1332.   {Find a label if it exists in the label chain}
  1333. var found : Boolean;
  1334. begin
  1335. pl := firstlabel; found := False;
  1336. while (pl <> nil) and not found do
  1337.   with pl^ do
  1338.     if symname = name then
  1339.       begin
  1340.       found := True;
  1341.       B := bytecnt;
  1342.       end
  1343.     else pl := next;
  1344. FindLabel := found;
  1345. end;
  1346.  
  1347. {-------------shortjmp}
  1348. FUNCTION shortjmp : Boolean;
  1349.   {short jump instructions}
  1350. const numjmp = 34;
  1351. type
  1352.   sjfield = array[0..numjmp] of array[1..5] of Char;
  1353.   opfield = array[0..numjmp] of Byte;
  1354. var I, B : Integer;
  1355. const
  1356.   jumps : sjfield = (
  1357.     'JO   ', 'JNO  ', 'JB   ', 'JNAE ', 'JNB  ', 'JAE  ',
  1358.     'JE   ', 'JZ   ', 'JNE  ', 'JNZ  ', 'JBE  ', 'JNA  ',
  1359.     'JNBE ', 'JA   ', 'LOOPN', 'LOOPZ', 'LOOPE', 'LOOP ',
  1360.     'JCXZ ', 'JS   ', 'JNS  ', 'JP   ', 'JPE  ', 'JNP  ',
  1361.     'JPO  ', 'JL   ', 'JNGE ', 'JNL  ', 'JGE  ', 'JLE  ',
  1362.     'JNG  ', 'JNLE ', 'JG   ', 'JC   ', 'JNC  ');
  1363.  
  1364.   opcode : opfield = (
  1365.     $70, $71, $72, $72, $73, $73, $74, $74, $75, $75, $76, $76,
  1366.     $77, $77, $e0, $e1, $e1, $e2, $e3, $78, $79, $7a, $7a, $7b,
  1367.     $7b, $7c, $7c, $7d, $7d, $7e, $7e, $7f, $7f, $72, $73);
  1368.  
  1369. begin shortjmp := False;
  1370. for I := 0 to numjmp do
  1371.   if Str = jumps[I] then
  1372.     begin
  1373.     InsertByte(opcode[I]);
  1374.     shortjmp := True;
  1375.     NoAddrs := True;
  1376.     NextA;
  1377.     if sym = identifier then
  1378.       begin
  1379.       if FindLabel(B) then
  1380.         begin
  1381.         Addr := B-(ByteCount+1);
  1382.         if Addr+$8080 <= $80ff then InsertByte(Lo(Addr))
  1383.         else Error(Chi, 'Too Far');
  1384.         end
  1385.       else
  1386.         begin               {enter jump into fixups}
  1387.         New(pf);
  1388.         with pf^ do
  1389.           begin
  1390.           next := firstfix;
  1391.           if firstfix <> nil then
  1392.             firstfix^.prev := pf;
  1393.           firstfix := pf;
  1394.           prev := nil;
  1395.           jmptype := short;
  1396.           name := symname;
  1397.           fix_pt := ByteCount; indx := tindex;
  1398.           InsertByte(0);     {dummy insertion}
  1399.           end;
  1400.         end;
  1401.       NextA;
  1402.       end
  1403.     else Error(Chi, 'Label Exp');
  1404.     end;
  1405. end;
  1406.  
  1407. {-------------ShfRot}
  1408. FUNCTION ShfRot : Boolean;
  1409. type
  1410.   instype = (rclx, rcrx, rolx, rorx, salx, sarx, shlx, shrx);
  1411.   nametype = array[rclx..shrx] of array[1..3] of Char;
  1412.   codetype = array[rclx..shrx] of Byte;
  1413. var
  1414.   inst : instype;
  1415.   cl : Byte;
  1416.  
  1417. const
  1418.   instname : nametype = (
  1419.     'RCL', 'RCR', 'ROL', 'ROR', 'SAL', 'SAR',
  1420.     'SHL', 'SHR');
  1421.  
  1422.   regcode : codetype = ($10, $18, 0, 8, $20, $38, $20, $28);
  1423.  
  1424. begin ShfRot := False;
  1425. if Lsid[0] = Chr(3) then
  1426.   for inst := rclx to shrx do
  1427.     if id3 = instname[inst] then
  1428.       begin
  1429.       NoAddrs := True; ShfRot := True;
  1430.       NextA;
  1431.       InsertByte($d0);       {may get modified later}
  1432.       if register(reg1, w1) then
  1433.         InsertByte($c0+regcode[inst]+reg1)
  1434.       else if MemReg(w2) then
  1435.         begin
  1436.         chk_bwptr;
  1437.         w1 := Ord(ByWord);
  1438.         InsertByte(modebyt+regcode[inst]);
  1439.         displace_bytes(w2);
  1440.         end
  1441.       else Error(Chi, 'Reg or Mem Exp');
  1442.       if sym = comma then NextA;
  1443.       cl := 0;
  1444.       if (id3 = 'CL ') then cl := 2
  1445.       else if nvalue <> 1 then Error(Chi, 'CL or 1 Exp');
  1446.       NextA;
  1447.       modify_byte(tindex0, cl+w1); {modify the opcode}
  1448.       end;
  1449. end;
  1450.  
  1451. {-------------CallJmp}
  1452. FUNCTION calljmp : Boolean;
  1453. type instype = (call, jmp);
  1454.   codetype = array[call..jmp] of Byte;
  1455. var
  1456.   inst : instype;
  1457.   dist : (nodist, long, shrt, near);
  1458.   tmp : Byte;
  1459.   dwtmp : ptrtype;
  1460.   B : Integer;
  1461.  
  1462. const
  1463.   shortop : codetype = ($e8, $e9);
  1464.   longop : codetype = ($9a, $ea);
  1465.   longcode : codetype = ($18, $28);
  1466.   shortcode : codetype = ($10, $20);
  1467.  
  1468. begin calljmp := False;
  1469. if Str = 'CALL ' then inst := call
  1470. else if Str = 'JMP  ' then inst := jmp
  1471. else Exit;
  1472.  
  1473. calljmp := True;
  1474. NextA;
  1475. dist := nodist;
  1476. dwtmp := ByWord;            {could have passed a 'DWORD PTR' here}
  1477. if sym = jmpdist then
  1478.   begin
  1479.   if id2 = 'FA' then dist := long
  1480.   else if id2 = 'NE' then dist := near
  1481.   else if id2 = 'SH' then dist := shrt;
  1482.   NextA;
  1483.   end;
  1484. if (sym = address) then
  1485.   begin
  1486.   InsertByte(longop[inst]);
  1487.   InsertWord(nvalue);
  1488.   InsertWord(segm);
  1489.   end
  1490. else if register(reg1, w1) then
  1491.   begin
  1492.   if w1 = 0 then wordreg;
  1493.   if dist = long then Error(Chi, 'FAR not Permitted');
  1494.   InsertByte($ff);
  1495.   InsertByte($c0+shortcode[inst]+reg1);
  1496.   end
  1497. else if sym = identifier then
  1498.   begin
  1499.   if dist = long then Error(Chi, 'Far not Permitted with Label');
  1500.   if FindLabel(B) then
  1501.     begin
  1502.     Addr := B-(ByteCount+2);
  1503.     if inst = call then
  1504.       begin
  1505.       InsertByte($e8);
  1506.       InsertWord(Addr-1);
  1507.       end
  1508.     else
  1509.       if (Addr+$8080 <= $80ff) and (dist <> near) then   {inst=jmp}
  1510.         begin               {short jump}
  1511.         InsertByte($eb); InsertByte(Lo(Addr));
  1512.         end
  1513.       else
  1514.         begin
  1515.         InsertByte($e9); InsertWord(Addr-1);
  1516.         end;
  1517.     end                     {findlabel}
  1518.   else
  1519.     begin                   {enter it into fixup chain}
  1520.     New(pf);
  1521.     with pf^ do
  1522.       begin
  1523.       next := firstfix;
  1524.       if firstfix <> nil then
  1525.         firstfix^.prev := pf;
  1526.       firstfix := pf;
  1527.       prev := nil;
  1528.       name := symname;
  1529.       if dist = shrt then
  1530.         begin
  1531.         jmptype := short;
  1532.         InsertByte($eb);
  1533.         fix_pt := ByteCount; indx := tindex;
  1534.         InsertByte(0);       {dummy insertion}
  1535.         end
  1536.       else
  1537.         begin
  1538.         jmptype := med;
  1539.         if inst = call then InsertByte($e8) else InsertByte($e9);
  1540.         fix_pt := ByteCount; indx := tindex;
  1541.         InsertByte(0);       {dummy insertion}
  1542.         indx2 := tindex;
  1543.         InsertByte(0);       {another dummy byte}
  1544.         end;
  1545.       end;
  1546.     end;
  1547.   end                       {identifier}
  1548. else if MemReg(w1) then
  1549.   begin
  1550.   if (dist = long) or (dwtmp = dwptr) then tmp := longcode[inst]
  1551.   else tmp := shortcode[inst];
  1552.   InsertByte($ff);
  1553.   InsertByte(modebyt+tmp);
  1554.   displace_bytes(w1);
  1555.   end
  1556. else errnull;
  1557. NextA;
  1558. end;
  1559.  
  1560. {-------------retrn}
  1561. PROCEDURE retrn(far : Boolean);
  1562. begin
  1563. if (sym = disp16) or (sym = disp8) then
  1564.   begin
  1565.   if far then InsertByte($ca) else InsertByte($c2);
  1566.   InsertWord(nvalue);
  1567.   NextA;
  1568.   end
  1569. else begin
  1570. if far then InsertByte($cb) else InsertByte($c3);
  1571. end;
  1572. end;
  1573.  
  1574. {-------------otherinst}
  1575. FUNCTION otherinst : Boolean;
  1576. label 2, 10, 20, 30;
  1577. type
  1578.   instsym = (ret, retf, aam, aad, inn, out, mul, imul, divd, idiv, Int);
  1579.   nametype = array[ret..Int] of array[1..5] of Char;
  1580. var index : instsym;
  1581.   tmp : Byte;
  1582. const instname : nametype = (
  1583.   'RET  ', 'RETF ', 'AAM  ', 'AAD  ', 'IN   ', 'OUT  ', 'MUL  ',
  1584.   'IMUL ', 'DIV  ', 'IDIV ', 'INT  ');
  1585.  
  1586.   PROCEDURE MulDiv(B : Byte);
  1587.   var wordbit : Integer;
  1588.   begin
  1589.   InsertByte($f6);
  1590.   if register(reg2, w2) then
  1591.     begin
  1592.     InsertByte($c0+B+reg2);
  1593.     wordbit := w2;
  1594.     end
  1595.   else if MemReg(w2) then
  1596.     begin
  1597.     chk_bwptr;
  1598.     wordbit := Ord(ByWord);
  1599.     InsertByte(modebyt+B);
  1600.     displace_bytes(w2);
  1601.     end
  1602.   else Error(Chi, 'Reg or Mem Exp');
  1603.   modify_byte(tindex0, wordbit);
  1604.   end;
  1605.  
  1606.   FUNCTION dxreg : Boolean;
  1607.   begin
  1608.   dxreg := False;
  1609.   if sym = identifier then
  1610.     if id2 = 'DX' then
  1611.       begin dxreg := True; NextA; end;
  1612.   end;
  1613.  
  1614.   FUNCTION accum(var W : Integer) : Boolean;
  1615.   var result_acc : Boolean;
  1616.     {See if next is AL or AX}
  1617.   begin
  1618.   result_acc := false;
  1619.   if (sym = identifier) then
  1620.     begin
  1621.     result_acc := (id3 = 'AX ') or (id3 = 'AL ');
  1622.     if result_acc then
  1623.       begin
  1624.       if Str[2] = 'X' then W := 1 else W := 0; {word vs byte register}
  1625.       NextA;
  1626.       end;
  1627.     end;
  1628.   accum := result_acc;
  1629.   end;
  1630.  
  1631. begin
  1632. otherinst := False;
  1633. for index := ret to Int do
  1634.   if Str = instname[index] then goto 2;
  1635. Exit;
  1636.  
  1637. 2: otherinst := True; NextA;
  1638. case index of
  1639.   ret : retrn(False);
  1640.   retf : retrn(True);
  1641.   out : begin
  1642.         if dxreg then InsertByte($ee) {out dx,ac}
  1643.         else if sym = disp8 then
  1644.           begin             {out port,ac}
  1645.           InsertByte($e6);
  1646.           InsertByte(Lo(nvalue));
  1647.           NextA;
  1648.           end
  1649.         else goto 10;
  1650.         if sym = comma then NextA;
  1651.         if accum(w1) then
  1652.           modify_byte(tindex0, w1) {al or ax}
  1653.         else goto 20;
  1654.         end;
  1655.   inn : begin
  1656.         if accum(w1) then
  1657.           begin
  1658.           if sym = comma then NextA;
  1659.           if dxreg then InsertByte($ec+w1) {in ac,dx}
  1660.           else
  1661.             begin
  1662.             if sym = disp8 then
  1663.               begin         {in ac,port}
  1664.               InsertByte($e4+w1);
  1665.               InsertByte(Lo(nvalue));
  1666.               NextA;
  1667.               end
  1668.             else
  1669.               10:Error(Chi, 'DX or Port Exp');
  1670.             end
  1671.           end
  1672.         else
  1673.           20:Error(Chi, 'AX or AL Exp');
  1674.         end;
  1675.   aam : begin
  1676.         tmp := $d4;
  1677.         goto 30;
  1678.         end;
  1679.   aad : begin
  1680.         tmp := $d5;
  1681.         30 : InsertByte(tmp);
  1682.         InsertByte($a);
  1683.         end;
  1684.   mul : MulDiv($20);
  1685.   imul : MulDiv($28);
  1686.   divd : MulDiv($30);
  1687.   idiv : MulDiv($38);
  1688.   int : begin
  1689.         if sym = disp8 then
  1690.           begin
  1691.           if nvalue = 3 then InsertByte($cc)
  1692.           else
  1693.             begin
  1694.             InsertByte($cd);
  1695.             InsertByte(Lo(nvalue));
  1696.             end;
  1697.           NextA;
  1698.           end
  1699.         else errnull;
  1700.         end;
  1701.  end;
  1702. end;
  1703.  
  1704. {-------------getquoted}
  1705. FUNCTION getquoted(var ls : bigstring) : Boolean;
  1706. var SaveChi, k : Integer;
  1707.   term : Char;
  1708.   gq : Boolean;
  1709. begin
  1710. skipspaces;
  1711. SaveChi := Chi; k := 1;
  1712. gq := False;
  1713. if (Uch = '''') or (Uch = '"') then
  1714.   begin
  1715.   term := Uch; GetCh;
  1716.   while (Uch <> term) and (Uch <> Chr(cr)) do
  1717.     if (Uch <> Chr(cr)) and (k <= bigstringsize) then
  1718.       begin
  1719.       ls[k] := Lch; k := k+1; GetCh;
  1720.       end;
  1721.   GetCh;                    {pass by term}
  1722.   gq := not(Uch in ['+', '-', '*', '/']); {else was meant to be expr}
  1723.   end;
  1724. ls[0] := Chr(k-1);
  1725. if not gq then
  1726.   begin Chi := SaveChi-1; GetCh; end;
  1727. getquoted := gq;
  1728. end;
  1729.  
  1730. {-------------databyte}
  1731. PROCEDURE databyte;
  1732. var I : Integer;
  1733.   Lst : bigstring;
  1734. begin
  1735. repeat
  1736.   if getquoted(Lst) then
  1737.     begin
  1738.     for I := 1 to Ord(Lst[0]) do
  1739.       InsertByte(Lo(Ord(Lst[I])));
  1740.     end
  1741.   else
  1742.     if readbyte then InsertByte(byt)
  1743.     else begin errnull; end;
  1744.   skipspaces;
  1745. until (Uch = Chr(cr)) or (Uch = ';') or aerr;
  1746. NextA;
  1747. end;
  1748.  
  1749. {-------------chk_for_label}
  1750. PROCEDURE chk_for_label;
  1751. Var dum1,dum2 : integer;
  1752. begin
  1753. if not prefix then          {could be prefix here}
  1754.   begin
  1755.   skipspaces;
  1756.   if (Lsid[0] > Chr(0)) and (Uch = ':') then
  1757.     begin                 {label found}
  1758.     sym := identifier;
  1759.     if register(dum1,dum2) then Error(Chi, 'Register name used as label')
  1760.     else
  1761.       begin
  1762.       GetCh; symname := Lsid;
  1763.       pl := firstlabel;       {check for duplication of label}
  1764.       while pl <> nil do
  1765.         with pl^ do
  1766.           begin
  1767.           if symname = name then Error(Chi, 'Duplicate Label');
  1768.           pl := next;
  1769.           end;
  1770.       New(pl);                {add the label to the label chain}
  1771.       with pl^ do
  1772.         begin
  1773.         next := firstlabel;
  1774.         firstlabel := pl;
  1775.         bytecnt := ByteCount;
  1776.         name := symname;
  1777.         end;
  1778.       pf := firstfix;         {see if any fixups are required}
  1779.       while pf <> nil do
  1780.         with pf^ do
  1781.           begin
  1782.           if name = symname then
  1783.             begin             {remove this fixup from chain}
  1784.             if pf = firstfix then
  1785.               firstfix := next
  1786.             else prev^.next := next;
  1787.             if next <> nil then next^.prev := prev;
  1788.             Dispose(pf);
  1789.             Addr := ByteCount-(fix_pt+1);
  1790.             if jmptype = short then
  1791.               begin
  1792.               if Addr+$80 <= $ff then modify_byte(indx, Lo(Addr))
  1793.               else Error(Chi, 'Too Far');
  1794.               end
  1795.             else
  1796.               begin           {jmptype=med}
  1797.               Addr := Addr-1;
  1798.               modify_byte(indx, Lo(Addr));
  1799.               modify_byte(indx2, Hi(Addr));
  1800.               end;
  1801.             end;
  1802.           pf := next;
  1803.           end;
  1804.       end;                    {label found}
  1805.     getstring;              {for next item to use}
  1806.     end;
  1807.   end                       {neither a label or a prefix}
  1808. else getstring;             {it was a prefix}
  1809. end;
  1810.  
  1811. {-------------interpret}
  1812. PROCEDURE interpret;
  1813. begin
  1814. tindex0 := tindex;          {opcode position}
  1815. getstring;
  1816. chk_for_label;
  1817. while prefix do             {process any prefix instructions}
  1818.   getstring;
  1819. if Lsid[0] > Chr(0) then
  1820.   begin
  1821.   if not NoOperand then
  1822.   if not OneOperand then
  1823.   if not TwoOperands then
  1824.   if not shortjmp then
  1825.   if not calljmp then
  1826.   if not ShfRot then
  1827.   if not otherinst then
  1828.   if not faddtype then
  1829.   if not fnoperand then
  1830.   if not fiaddtype then
  1831.   if not fldtype then
  1832.   if not fmemonly then
  1833.   if not fildtype then
  1834.   if not fstionly then
  1835.   if id3 = 'DB ' then databyte
  1836.   else if Lsid = 'NEW' then begin NewFnd:=true; NextA; end
  1837.   else if Lsid = 'END' then
  1838.     begin
  1839.     TheEnd := True;
  1840.     NextA;
  1841.     end
  1842.   else Error(Chi, 'Unknown Instruction');
  1843.   end
  1844. else
  1845.   NextA;                 {if not a string find out what}
  1846. if sym <> EOLsym then Error(Chi, 'End of Line Exp');
  1847. end;
  1848.  
  1849. {-------------chk_ioerror}
  1850. FUNCTION chk_ioerror(S : filestring): Integer;
  1851. var ioerr : Integer;
  1852. begin
  1853. ioerr := IOResult;
  1854. if ioerr = 1 then WriteLn('Can''t find ', S)
  1855. else if ioerr <> 0 then WriteLn('I/O Error ', Hex4(ioerr));
  1856. chk_ioerror := ioerr;
  1857. end;
  1858.  
  1859. {-------------PromptForInput}
  1860. PROCEDURE PromptForInput;
  1861. var
  1862.   inname,name : filestring;
  1863.   err : Integer;
  1864. begin
  1865. {$I-}
  1866. Repeat
  1867.   Write('Source Filename [.ASM]: '); ReadLn(inname);
  1868.   if inname='' then Halt;
  1869.   DefaultExtension('ASM', inname, name);
  1870.   Assign(inn, inname); Reset(inn);
  1871.   err:=chk_ioerror(inname);
  1872.   if err>1 then Halt(1);
  1873. until err=0;
  1874. Write('Object Filename [', name, '.OBJ]: '); ReadLn(inname);
  1875. if inname='' then inname:=name;   {Use the same name}
  1876. DefaultExtension('OBJ',inname,name);
  1877. Assign(out, inname);
  1878. ReWrite(out);
  1879. if chk_ioerror(inname)<>0 then Halt(1);
  1880. {$I+}
  1881. end;
  1882.  
  1883. {-------------CommandInput}
  1884. PROCEDURE CommandInput;
  1885. var
  1886.   inname,name : filestring;
  1887. begin
  1888. inname:=ParamStr(1);
  1889. DefaultExtension('ASM', inname, name);
  1890. {$I-}
  1891. Assign(inn, inname);
  1892. ReSet(inn);
  1893. if chk_ioerror(inname)<>0 then Halt(1);
  1894. if ParamCount>=2 then inname:=ParamStr(2)
  1895.   else inname:=name;             {Use the old name}
  1896. DefaultExtension('OBJ',inname,name);
  1897. Assign(out, inname);
  1898. ReWrite(out);
  1899. if chk_ioerror(inname)<>0 then Halt(1);
  1900. {$I+}
  1901. end;
  1902.  
  1903. {-------------LabelReport}
  1904. PROCEDURE LabelReport;  {Report any fixups not made and restore heap}
  1905. var
  1906.   pftmp : fixup_info_ptr;
  1907.   pltmp : label_info_ptr;
  1908. begin
  1909. pf := firstfix;
  1910. while pf <> nil do
  1911.   with pf^ do
  1912.     begin
  1913.     WriteLn('Label not Found-- ', name);
  1914.     pftmp := next;
  1915.     Dispose(pf);
  1916.     pf:=pftmp;
  1917.     end;
  1918. pl := firstlabel;
  1919. while pl <> nil do
  1920.   begin
  1921.   pltmp := pl^.next;
  1922.   Dispose(pl);
  1923.   pl:=pltmp;
  1924.   end;
  1925. end;
  1926.  
  1927. {-------------main}
  1928. begin
  1929. Write(signon1); WriteLn(signon2);
  1930. if ParamCount >= 1 then CommandInput else PromptForInput;
  1931.  
  1932. Wait_Already:=False;
  1933. NewFnd:=true;
  1934. while NewFnd and not EoF(inn) do
  1935.   begin
  1936.   NewFnd:=false;
  1937.   start_col := 1; TheEnd := False;
  1938.   tindex := 0;
  1939.   ByteCount := 0;
  1940.   firstlabel := nil; firstfix := nil;
  1941.   InsertStr('Inline('+^m^j);
  1942.   str_start := True;
  1943.  
  1944.   while not EoF(inn) and not TheEnd and not NewFnd do
  1945.     begin
  1946.     aerr := False; NoAddrs := False;
  1947.     ByWord := unkptr;
  1948.     column := 0;
  1949.     ReadLn(inn, st); Chi := 1; GetCh; sym := othersym;
  1950.     SkipSpaces;
  1951.     if Uch<>chr(CR) then   {skip blank lines}
  1952.       begin
  1953.       InsertStr('  ');
  1954.       interpret;
  1955.       if not NewFnd then
  1956.         begin
  1957.         while column < CommentColumn do InsertChr(' ');
  1958.         InsertChr('{');
  1959.         I := 1;
  1960.         while (column < 124) and (I <= Length(st)) do
  1961.           begin
  1962.           InsertChr(st[I]);
  1963.           I := I+1;
  1964.           end;
  1965.         InsertStr('}'^m^j);
  1966.         end;
  1967.       end;
  1968.     end;
  1969.   InsertStr(');'^m^j);
  1970.   LabelReport;       {report any fixups not made and dispose all heap items}
  1971.   for I := 0 to tindex-1 do Write(out, TextArray[I]);
  1972.   end;
  1973. Close(out);
  1974. Close(inn);
  1975. end.
  1976.